const _fs = require('fs')
const {
	fork: _fork,
	exec: _exec,
} = require('child_process');
const _numCPUs = require('os').cpus().length;
const {
	getMSTime,
} = require('../index')
const _CrawlerMongo = require('../config/CrawlerMongo')
const _mongo = new _CrawlerMongo()

module.exports = class TaskBaseMaster {

	constructor(options = {}) {
		let num = parseInt(options.num) || 1
		this.num = num > _numCPUs ? _numCPUs : num < 1 ? 1 : num
		this.filter = options.filter
		this.bash = options.bash
	}

	start() {
		return start.call(this)
	}

	run() {
		return run.call(this, -1)
	}

	childKill() {
		return Promise.resolve()
	}

	stopTask(pid) {
		return stopTask.call(this, pid)
	}
}

async function start() {
	console.log('---this.filter---', this.filter)
	this.num = this.num > _numCPUs ? _numCPUs : this.num < 1 ? 1 : this.num
	if (!this.filter || !this.filter['_type_.id'] || !this.filter['_cate_.id']) {
		console.log('---[filter条件错误！！！]---')
		process.exit(1)
	}
	if (!this.bash || !this.bash.child_process || !this.bash.cmd) {
		let collection = await _mongo.getCollection('task')
		let task = await collection.findOne(this.filter)
		this.bash = task._bash_
	}
	for (let i = 0; i < this.num; i++)
		await run.call(this, i)
	return 'success'
}

/**
 * [run description]
 * @param  {[type]} idx [description]
 * @return {[type]}     [description]
 */
async function run(idx) {
	let result = await checkOver.call(this)
	if (result === true) {
		console.log('---没有任务！！！----')
		return setTimeout(() => {
			process.exit(0)
		}, 1000)
	}
	let {
		cmd,
		args = [],
		params,
		options = {},
		child_process,
	} = this.bash
	cmd = cmd.replace('#{_id}.log', `${idx}.log`)
	for (let key in params) {
		let val = params[key] || ''
		cmd = cmd.replace(new RegExp(key, 'g'), val)
	}
	let child = null
	if (child_process == 'exec')
		child = _exec(cmd, options)
	else if (child_process == 'fork')
		child = _fork(cmd, args, options)
	let pid = child && child.pid || ''
	if (!pid)
		return false
	let stop = false
	child.on('message', message => {
		if (typeof message.kill == 'number') {
			stop = message.stop
			child.kill(message.kill)
			if (idx > -1)
				this.childKill(message)
		}
	})
	child.on('exit', data => {
		stopTask.call(this, pid).then(r => {
			if (!stop)
				run.call(this, idx)
		})
	})
}

async function stopTask(pid) {
	if (!pid) {
		console.log('没有pid！！！')
		process.exit(1)
	}
	let update = 'findOneAndUpdate'
	this.filter.pid = pid
	if (Array.isArray(pid)) {
		update = 'updateMany'
		this.filter.pid = {
			$in: pid
		}
	}
	this.filter.status = 1
	let collection = await _mongo.getCollection('task')
	return collection[update](this.filter, {
		$set: {
			pid: -1,
			status: 2,
			_stop: '---中断---',
			modify_time: getMSTime(),
		}
	})
}

async function checkOver() {
	let collection = await _mongo.getCollection('task')
	let typeId = this.filter['_type_.id']
	let cateId = this.filter['_cate_.id']
	// let count = await collection.count({
	// 	'_type_.id': typeId,
	// 	'_cate_.id': cateId,
	// })
	// let success = await collection.count({
	// 	'_type_.id': typeId,
	// 	'_cate_.id': cateId,
	// 	status: -1,
	// })
	let waiting = await collection.count({
		'_type_.id': typeId,
		'_cate_.id': cateId,
		status: 0,
	})
	return waiting === 0
}